/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package fh.controller;

import fh.component.DataSource;
import fh.model.Event;
import fh.model.Player;
import fh.model.Round;
import fh.model.Table;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JOptionPane;

/**
 *
 * @author Dikkehein
 */
public class RunTourneyController {

    public Event runningEvent;
    public int tables;
    public int currentRoundNumber;
    public int payedPlayers;

    public RunTourneyController(Event e) {
        runningEvent = e;

        currentRoundNumber = selectCurrentRound().getRound_number();
        payedPlayers = getPayedPlayers().size();
        if (selectCurrentRound().getRound_number() == 0) {
            tables = 0;
        } else {
            tables = getTableList(selectCurrentRound()).size();
        }

    }

    private int calculateInitialTables() {
        int t = payedPlayers / runningEvent.getTable_cap();
        int r = payedPlayers % runningEvent.getTable_cap();
        if (r > 0) {
            t++;
        }
        return t;
    }

    public void startTourney() {
        tables = calculateInitialTables();
        List<Player> playerList = getPayedPlayers();
        if (playerList.size() > 1) {
            currentRoundNumber++;
            createRound();
            createTables();
            createTablePlaces(getPayedPlayers());
        } else {
            JOptionPane.showMessageDialog(null, "Er zijn te weinig spelers ingeschreven.");
        }
    }

    private void createTables() {
        Round currentRound = selectCurrentRound();
        for (int i = 0; i < tables; i++) {
            String insertTableQuery = "INSERT INTO `table` (`table_number`, `round_id`) VALUES ('"
                    + i++ + "', '"
                    + currentRound.getId() + "')";
            System.out.println(insertTableQuery);
            DataSource.executeUpdateQuery(insertTableQuery);
        }
    }

    private boolean createRound() {
        String insertRoundQuery = "INSERT INTO `round` (`round_number`, `event_id`) VALUES ('"
                + currentRoundNumber + "', '"
                + runningEvent.getId() + "')";
        System.out.println(insertRoundQuery);
        DataSource.executeUpdateQuery(insertRoundQuery);
        return true;
    }

    public Round selectCurrentRound() {
        try {
            Round cr;

            String selectRoundQuery = "SELECT * FROM round WHERE event_id='"
                    + runningEvent.getId() + "' ORDER BY round_number desc limit 1";

            ResultSet rs = DataSource.executeSelectQuery(selectRoundQuery);
            if (rs != null) {
                cr = new Round();
                while (rs.next()) {
                    cr.setId(rs.getInt(1));
                    cr.setRound_number(rs.getInt(2));
                    cr.setEvent_id(rs.getInt(3));
                }
                return cr;
            } else {
                return null;
            }
        } catch (SQLException e) {
            System.out.println("Deze error:");
            System.out.println(e);
            return null;
        }

    }

    private List<Player> getPayedPlayers() {
        try {
            List<Player> playerList = new ArrayList<Player>();

            String query = "SELECT * FROM player P INNER JOIN player_event PE ON  P.id=PE.player_id WHERE event_id='" + runningEvent.getId() + "' AND payed=1";

            ResultSet rs = DataSource.executeSelectQuery(query);
            if (rs != null) {
                Player p;
                while (rs.next()) {
                    p = new Player();
                    p.setId(rs.getInt(1));
                    p.setFirstname(rs.getString(2));
                    p.setLastname(rs.getString(3));
                    p.setAddress(rs.getString(4));
                    p.setZipcode(rs.getString(5));
                    p.setCity(rs.getString(6));
                    p.setPhonenumber(rs.getString(7));
                    p.setEmail(rs.getString(8));
                    p.setRating(rs.getInt(9));
                    p.setMoney_won(rs.getInt(10));
                    p.setVip(rs.getBoolean(11));

                    playerList.add(p);
                }

                return playerList;
            } else {
                return null;
            }
        } catch (SQLException e) {
            System.out.println("Deze error:");
            System.out.println(e);
            return null;
        }
    }

    public List<Table> getTableList(Round r) {
        try {
            List<Table> tableList = new ArrayList<Table>();

            String query = "SELECT * FROM `table` WHERE round_id=" + r.getId();

            ResultSet rs = DataSource.executeSelectQuery(query);
            if (rs != null) {
                Table t;
                while (rs.next()) {
                    t = new Table();
                    t.setId(rs.getInt(1));
                    t.setTable_number(rs.getInt(2));
                    t.setRound_id(rs.getInt(3));
                    tableList.add(t);
                }

                return tableList;
            } else {
                return null;
            }
        } catch (SQLException e) {
            System.out.println("Deze error:");
            System.out.println(e);
            return null;
        }


    }

    public void createTablePlaces(List<Player> pl) {


        List<Table> tableList = getTableList(selectCurrentRound());
        List<Player> draftedPlayers = new ArrayList<Player>();

        int i = 0;
        while (draftedPlayers.size() < pl.size()) {
            for (Table t : tableList) {
                if (i < pl.size()) {
                    Player p = pl.get(i);
                    String insertPlayerTableQuery = "INSERT INTO `player_table` (`player_id`, `table_id`, `table_rank`) VALUES ('"
                            + p.getId() + "', '"
                            + t.getId() + "', '0')";
                    System.out.println(insertPlayerTableQuery);
                    DataSource.executeUpdateQuery(insertPlayerTableQuery);
                    draftedPlayers.add(p);
                    i++;

                } else {
                    break;
                }
            }
        }

    }

    public List<Player> getPlayersForTable(Table t) {
        try {
            List<Player> playerList = new ArrayList<Player>();

            String query = "SELECT * FROM player P INNER JOIN player_table PT ON P.id=PT.player_id WHERE table_id=" + t.getId();

            ResultSet rs = DataSource.executeSelectQuery(query);
            if (rs != null) {
                Player p;
                while (rs.next()) {
                    p = new Player();
                    p.setId(rs.getInt(1));
                    p.setFirstname(rs.getString(2));
                    p.setLastname(rs.getString(3));
                    p.setAddress(rs.getString(4));
                    p.setZipcode(rs.getString(5));
                    p.setCity(rs.getString(6));
                    p.setPhonenumber(rs.getString(7));
                    p.setEmail(rs.getString(8));
                    p.setRating(rs.getInt(9));
                    p.setMoney_won(rs.getInt(10));
                    p.setVip(rs.getBoolean(11));

                    playerList.add(p);
                }

                return playerList;
            } else {
                return null;
            }
        } catch (SQLException e) {
            System.out.println("Deze error:");
            System.out.println(e);
            return null;
        }
    }

    private List<Player> getPlayersForTableByRanking(Table t) {
        try {
            List<Player> playerList = new ArrayList<Player>();

            String query = "SELECT * FROM player P INNER JOIN player_table PT ON P.id=PT.player_id WHERE table_id="
                    + t.getId() + " ORDER BY table_rank DESC";

            ResultSet rs = DataSource.executeSelectQuery(query);
            if (rs != null) {
                Player p;
                while (rs.next()) {
                    p = new Player();
                    p.setId(rs.getInt(1));
                    p.setFirstname(rs.getString(2));
                    p.setLastname(rs.getString(3));
                    p.setAddress(rs.getString(4));
                    p.setZipcode(rs.getString(5));
                    p.setCity(rs.getString(6));
                    p.setPhonenumber(rs.getString(7));
                    p.setEmail(rs.getString(8));
                    p.setRating(rs.getInt(9));
                    p.setMoney_won(rs.getInt(10));
                    p.setVip(rs.getBoolean(11));

                    playerList.add(p);
                }

                return playerList;
            } else {
                return null;
            }
        } catch (SQLException e) {
            System.out.println("Deze error:");
            System.out.println(e);
            return null;
        }
    }

    private Player getHighestRatingForTable(Table t) {
        try {
            Player p = new Player();

            String query = "SELECT * FROM player P INNER JOIN player_table PT ON P.id=PT.player_id WHERE table_id="
                    + t.getId() + "  ORDER BY rating DESC LIMIT 1";

            ResultSet rs = DataSource.executeSelectQuery(query);
            if (rs != null) {
                while (rs.next()) {
                    p.setId(rs.getInt(1));
                    p.setFirstname(rs.getString(2));
                    p.setLastname(rs.getString(3));
                    p.setAddress(rs.getString(4));
                    p.setZipcode(rs.getString(5));
                    p.setCity(rs.getString(6));
                    p.setPhonenumber(rs.getString(7));
                    p.setEmail(rs.getString(8));
                    p.setRating(rs.getInt(9));
                    p.setMoney_won(rs.getInt(10));
                    p.setVip(rs.getBoolean(11));


                }

                return p;
            } else {
                return null;
            }
        } catch (SQLException e) {
            System.out.println("Deze error:");
            System.out.println(e);
            return null;
        }

    }

    public boolean saveTableWinner(Table t, Player p, int place) {
        String updateQuery = "UPDATE `player_table` SET `table_rank`='"
                + place + "' WHERE `player_id`='"
                + p.getId() + "' AND `table_id`='"
                + t.getId() + "'";

        DataSource.executeUpdateQuery(updateQuery);
        return true;
    }

    public boolean checkFreeTableRank(Table t, int place) {
        try {
            String countQuery = "SELECT COUNT(`player_id`) FROM player_table WHERE `table_id`='"
                    + t.getId() + "' AND `table_rank`='"
                    + place + "'";

            ResultSet rs = DataSource.executeSelectQuery(countQuery);
            if (rs != null) {
                int count = -1;
                while (rs.next()) {
                    count = rs.getInt(1);
                }
                if (count != 0) {
                    return false;
                } else {
                    return true;
                }

            } else {
                return false;
            }
        } catch (SQLException e) {
            System.out.println("Deze error:");
            System.out.println(e);
            return false;
        }
    }

    public int selectTableRank(Table t, Player p) {
        try {
            int place = 0;

            String query = "SELECT table_rank FROM `player_table` WHERE `table_id`='"
                    + t.getId() + "' AND `player_id`='"
                    + p.getId() + "'";

            ResultSet rs = DataSource.executeSelectQuery(query);
            if (rs != null) {

                while (rs.next()) {
                    place = rs.getInt(1);
                }

                return place;
            } else {
                return 0;
            }
        } catch (SQLException e) {
            System.out.println("Deze error:");
            System.out.println(e);
            return 0;
        }

    }

    private List<Player> getTableWinners() {

        Round r = selectCurrentRound();

        List<Table> tl = getTableList(r);

        List<Player> playerList = new ArrayList<Player>();
        for (Table t : tl) {
            try {
                String query = "SELECT * FROM player P INNER JOIN player_table PT ON P.id=PT.player_id WHERE table_id="
                        + t.getId() + " AND table_rank = 1";

                ResultSet rs = DataSource.executeSelectQuery(query);
                if (rs != null) {
                    Player p;
                    while (rs.next()) {
                        p = new Player();
                        p.setId(rs.getInt(1));
                        p.setFirstname(rs.getString(2));
                        p.setLastname(rs.getString(3));
                        p.setAddress(rs.getString(4));
                        p.setZipcode(rs.getString(5));
                        p.setCity(rs.getString(6));
                        p.setPhonenumber(rs.getString(7));
                        p.setEmail(rs.getString(8));
                        p.setRating(rs.getInt(9));
                        p.setMoney_won(rs.getInt(10));
                        p.setVip(rs.getBoolean(11));

                        playerList.add(p);
                    }

                } else {
                }
            } catch (SQLException e) {
                System.out.println("Deze error:");
                System.out.println(e);
                return null;
            }

        }
        return playerList;
    }

    public void startNextRound() {
        updateRating();
        List<Player> playerList = getTableWinners();

        tables = calculateNextRoundTables(playerList.size());
        if (tables != 0) {
            createNextRound();
            createTables();
            createTablePlaces(playerList);
        } else {
            tables = 1;
            JOptionPane.showMessageDialog(null, "De laatste ronde heeft al plaats gevonden.");
        }
    }

    private int calculateNextRoundTables(int leftOver) {
        if (tables != 1) {
            int t = leftOver / runningEvent.getTable_cap();
            int r = leftOver % runningEvent.getTable_cap();
            if (r > 0) {
                t++;
            }
            return t;
        } else {
            return 0;
        }
    }

    private void createNextRound() {
        currentRoundNumber++;

        createRound();
    }

    public void updateRating() {
        Round r = selectCurrentRound();
        List<Table> tl = getTableList(r);

        for (Table t : tl) {
            List<Player> pl = getPlayersForTableByRanking(t);
            Player p = getHighestRatingForTable(t);
            calculateRating(pl, p);
        }
    }

    private void calculateRating(List<Player> pl, Player highestRatingPlayer) {
        for (int i = 0; i < (pl.size() - 1); i++) {

            double loserRating = Math.round(((double) pl.get(i).getRating() / (double) pl.get(i + 1).getRating()) * 10.0);
            int newLoserRating = pl.get(i).getRating() - (int) loserRating;
            pl.get(i).setRating(newLoserRating);
        }
        double winnerRating = Math.round((double) highestRatingPlayer.getRating() / (double) pl.get(pl.size() - 1).getRating()) * 10;
        int newWinnerRating = pl.get(pl.size() - 1).getRating() + (int) winnerRating;
        pl.get(pl.size() - 1).setRating(newWinnerRating);

        savePlayerRating(pl);

    }

    private void savePlayerRating(List<Player> pl) {
        for (Player p : pl) {
            String insertPlayerQuery = "UPDATE `player` SET "
                    + "rating = '" + p.getRating() + "'"
                    + " WHERE id = '" + p.getId() + "'";
            DataSource.executeUpdateQuery(insertPlayerQuery);
        }
    }
}